[OpenGL ES - Android] Better way to generate tiles

Posted by Inoe on Stack Overflow See other posts from Stack Overflow or by Inoe
Published on 2010-03-15T00:20:23Z Indexed on 2010/03/15 0:29 UTC
Read the original article Hit count: 1104

Filed under:
|
|
|

Hi !

I'll start by saying that i'm REALLY new to OpenGL ES (I started yesterday =), but I do have some Java and other languages experience.

I've looked a lot of tutorials, of course Nehe's ones and my work is mainly based on that.

As a test, I started creating a "tile generator" in order to create a small Zelda-like game (just moving a dude in a textured square would be awsome :p).

So far, I have achieved a working tile generator, I define a char map[][] array to store wich tile is on :

private char[][] map = {
            {0, 0, 20, 11, 11, 11, 11, 4, 0, 0},
            {0, 20, 16, 12, 12, 12, 12, 7, 4, 0},
            {20, 16, 17, 13, 13, 13, 13, 9, 7, 4},
            {21, 24, 18, 14, 14, 14, 14, 8, 5, 1},
            {21, 22, 25, 15, 15, 15, 15, 6, 2, 1},
            {21, 22, 23, 0, 0, 0, 0, 3, 2, 1},
            {21, 22, 23, 0, 0, 0, 0, 3, 2, 1},
            {26, 0, 0, 0, 0, 0, 0, 3, 2, 1},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
            {0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
    };

It's working but I'm no happy with it, I'm sure there is a beter way to do those things :

1) Loading Textures :

I create an ugly looking array containing the tiles I want to use on that map :

private int[] textures = {
            R.drawable.herbe, //0
            R.drawable.murdroite_haut, //1
            R.drawable.murdroite_milieu, //2
            R.drawable.murdroite_bas, //3
            R.drawable.angledroitehaut_haut, //4
            R.drawable.angledroitehaut_milieu,  //5
    };

(I cutted this on purpose, I currently load 27 tiles)

All of theses are stored in the drawable folder, each one is a 16*16 tile.

I then use this array to generate the textures and store them in a HashMap for a later use :

int[] tmp_tex = new int[textures.length]; 
            gl.glGenTextures(textures.length, tmp_tex, 0); 
            texturesgen = tmp_tex; //Store the generated names in texturesgen 
            for(int i=0; i < textures.length; i++)
            { 
                    //Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), textures[i]);
                    InputStream is = context.getResources().openRawResource(textures[i]);
                    Bitmap bitmap = null;
                    try {
                        //BitmapFactory is an Android graphics utility for images
                        bitmap = BitmapFactory.decodeStream(is);

                    } finally {
                        //Always clear and close
                        try {
                            is.close();
                            is = null;
                        } catch (IOException e) {
                        }
                    } 
                    // Get a new texture name 
                    // Load it up 
                    this.textureMap.put(new Integer(textures[i]),new Integer(i)); 
                    int tex = tmp_tex[i]; 
                    gl.glBindTexture(GL10.GL_TEXTURE_2D, tex); 
                    //Create Nearest Filtered Texture
                    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
                    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

                    //Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
                    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
                    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);

                    //Use the Android GLUtils to specify a two-dimensional texture image from our bitmap
                    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

                    bitmap.recycle();
            } 

I'm quite sure there is a better way to handle that... I just was unable to figure it. If someone has an idea, i'm all ears.

2) Drawing the tiles

What I did was create a single square and a single texture map :

/** The initial vertex definition */
    private float vertices[] = { 
                                -1.0f, -1.0f, 0.0f,     //Bottom Left
                                1.0f, -1.0f, 0.0f,      //Bottom Right
                                -1.0f, 1.0f, 0.0f,      //Top Left
                                1.0f, 1.0f, 0.0f        //Top Right
                                                };

    private float texture[] = {         
            //Mapping coordinates for the vertices
              0.0f, 1.0f,
              1.0f, 1.0f,
              0.0f, 0.0f,
              1.0f, 0.0f

                                };

Then, in my draw function, I loop through the map to define the texture to use (after pointing to and enabling the buffers) :

for(int y = 0; y < Y; y++){
            for(int x = 0; x < X; x++){
                tile = map[y][x];
                try 
                    { 
                                   //Get the texture from the HashMap
                       int textureid = ((Integer) this.textureMap.get(new Integer(textures[tile]))).intValue(); 
                       gl.glBindTexture(GL10.GL_TEXTURE_2D, this.texturesgen[textureid]); 
                    }    
                    catch(Exception e) 
                    { 
                      return; 
                    }

                //Draw the vertices as triangle strip
                gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);            
                gl.glTranslatef(2.0f, 0.0f, 0.0f); //A square takes 2x so I move +2x before drawing the next tile
            }
            gl.glTranslatef(-(float)(2*X), -2.0f, 0.0f); //Go back to the begining of the map X-wise and move 2y down before drawing the next line
        }

This works great by I really think that on a 1000*1000 or more map, it will be lagging as hell (as a reminder, this is a typical Zelda world map : http://vgmaps.com/Atlas/SuperNES/LegendOfZelda-ALinkToThePast-LightWorld.png ).

I've read things about Vertex Buffer Object and DisplayList but I couldn't find a good tutorial and nodoby seems to be OK on wich one is the best / has the better support (T1 and Nexus One are ages away).

I think that's it, I've putted a lot of code but I think it helps.

Thanks in advance !

© Stack Overflow or respective owner

Related posts about android

Related posts about opengl-es